#include <iostream>
#include <math.h>
#define int long long
using namespace std;


int l2(int x){
	return (int)log2(x)+2;
}


int p2(int x){
	return (int)pow(2,x);
}


struct node{
	int left=-1,right=-1,lindex=-1,rindex=-1;
	int sum=0,tagt=1,taga=0;
	void cac(int t,int a,int m){
		tagt *= t;
		taga *= t;
		taga += a;
		taga %= m;
		tagt %= m;
		return;
	}
	int ask(int m){
        sum %= m;
		return (sum*tagt%m+taga*(right-left+1)%m)%m;
	}
};


int index=-1;
int build(int l,int r,int a[],node tree[]){
	index++;
	tree[index].left = l;
	tree[index].right = r;
	
	
	if(l == r){
		tree[index].sum = a[l];
		return index;
	}
	
	int mid=(l+r)/2;
	int nowi=index;
	tree[nowi].lindex = build(l,mid,a,tree);
	tree[nowi].rindex = build(mid+1,r,a,tree);
	tree[nowi].sum = tree[tree[nowi].lindex].sum+tree[tree[nowi].rindex].sum;
	return nowi;
}


int change(int l,int r,int ind,int t,int a,node tree[],int m){
	if(tree[ind].left >= l  &&  tree[ind].right <= r){
		tree[ind].cac(t,a,m);
		return tree[ind].ask(m);
	}
	
	int tx,ax;
	tree[ind].sum = tree[ind].ask(m);
	tx = tree[ind].tagt;
	ax = tree[ind].taga;
	tree[ind].tagt = 1;
	tree[ind].taga = 0;
	
	tree[tree[ind].lindex].cac(tx,ax,m);
	tree[tree[ind].rindex].cac(tx,ax,m);
	
	
	int s1=tree[tree[ind].lindex].ask(m),s2=tree[tree[ind].rindex].ask(m);
	if(tree[tree[ind].lindex].left <= r  &&  tree[tree[ind].lindex].right >= l)
		s1 = change(l,r,tree[ind].lindex,t,a,tree,m);
	if(tree[tree[ind].rindex].left <= r  &&  tree[tree[ind].rindex].right >= l)
		s2 = change(l,r,tree[ind].rindex,t,a,tree,m);
	tree[ind].sum = s1+s2;
	return (s1+s2)%m;
}


int get(int l,int r,int ind,node tree[],int m){
	if(tree[ind].left >= l  &&  tree[ind].right <= r){
		return tree[ind].ask(m);
	}
	
	tree[ind].sum = tree[ind].ask(m);
	int t=tree[ind].tagt,a=tree[ind].taga;
	tree[tree[ind].lindex].cac(t,a,m);
	tree[tree[ind].rindex].cac(t,a,m);
	tree[ind].taga = 0;
	tree[ind].tagt = 1;
	
	int sum=0;
	if(tree[tree[ind].lindex].left <= r  &&  tree[tree[ind].lindex].right >= l)
		sum += get(l,r,tree[ind].lindex,tree,m);
	if(tree[tree[ind].rindex].left <= r  &&  tree[tree[ind].rindex].right >= l)
		sum += get(l,r,tree[ind].rindex,tree,m);
	return sum%m;
}



signed main(){
	int n,q,m;
	cin>>n>>q>>m;
	int nn=p2(l2(n));
	node tree[p2(l2(n))];
	int a[n];
	for(int i=0;i<n;i++){
		cin>>a[i];
	}
	build(0,n-1,a,tree);
	
	
	for(int i=0;i<q;i++){
		int org,x,y;
		cin>>org>>x>>y;
		x--;
		y--;
		
		
		if(org == 1){
			int k;
			cin>>k;
			change(x,y,0,k,0,tree,m);
		}
		else if(org == 2){
			int k;
			cin>>k;
			change(x,y,0,1,k,tree,m);
		}
		else{
			cout<<get(x,y,0,tree,m)<<endl;
		}
//		cout<<endl;
//		cout<<i<<endl;
//		for(int j=0;j<nn;j++){
//			cout<<j<<" "<<tree[j].left<<" "<<tree[j].right<<" "<<tree[j].lindex<<" "<<tree[j].rindex<<" "<<tree[j].taga<<" "<<tree[j].tagt<<" "<<tree[j].sum<<endl;
//		}
//		cout<<endl<<endl;
	}
	return 0;
}
